package ai.fabu.dataplatform.service.GRPCServer;


import ai.fabu.dataplatform.*;
import ai.fabu.dataplatform.bean.framedata.GetBinData;
import ai.fabu.dataplatform.bean.util.IndexData;
import ai.fabu.dataplatform.constant.ResultCode;
import ai.fabu.dataplatform.help.Result;
import ai.fabu.dataplatform.service.ApiForImportBagService;
import ai.fabu.dataplatform.service.ApiService;
import com.google.protobuf.ByteString;
import com.mongodb.MongoException;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.UncategorizedMongoDbException;

import java.util.ArrayList;
import java.util.List;

import static ai.fabu.dataplatform.constant.ConstantValue.RETRY_TIME;

@Slf4j
public class DataPlatformBinDataServer {
    @GrpcService(BinDataServiceGrpc.class)
    private static class DataPlatformBinDataImpl extends BinDataServiceGrpc.BinDataServiceImplBase{
        @Autowired
        ApiForImportBagService apiForImportBagService;
        @Autowired
        ApiService apiService;

        @Override
        public void getBinData(GetBinDataRequest request, StreamObserver<GetBinDataResponse> responseObserver) {
            Result<List<GetBinData>> result;
            try{
                Index index = request.getIndex();
                IndexData indexData = new IndexData(index.getGroupName(), index.getBagName(), index.getTopicName(), index.getFrameNo());
                result = apiService.getBinData(indexData);
            }
            catch (Exception e){
                FunctionUtil.errorHandler(responseObserver, "getBinData", ResultCode.SYSTEM_ERROR.getMsg());
                throw e;
            }
            if(result.getCode() == ResultCode.SUCCESS.getCode()){
                List<GetBinData> dataList = result.getData();
                dataList.forEach(data -> {
                    Index index = Index.newBuilder().setGroupName(data.getIndexData().getGroupName()).setBagName(data.getIndexData().getBagName())
                            .setTopicName(data.getIndexData().getTopicName()).setFrameNo(data.getIndexData().getFrameNo()).build();
                    GetBinDataResponse response = GetBinDataResponse.newBuilder().setIndex(index).setData(ByteString.copyFrom(data.getBinData())).build();
                    responseObserver.onNext(response);
                });
                responseObserver.onCompleted();
            }
            else
                FunctionUtil.errorHandler(result, responseObserver, "getBinData");
        }

        @Override
        public void saveBinData(SaveBinDataRequest request, StreamObserver<SaveResponse> responseObserver) {
            Index index = request.getIndex();
            IndexData indexData = new IndexData(index.getGroupName(), index.getBagName(), index.getTopicName(), index.getFrameNo());
            List<String> binPathList = new ArrayList<>(request.getBinPathsList());
            Result<Long> result;
            try{
                result = apiForImportBagService.saveBinData(indexData, binPathList);
            } catch (Exception e) {
                FunctionUtil.errorHandler(responseObserver, "saveBinData", ResultCode.SYSTEM_ERROR.getMsg());
                throw e;
            }
            if(result.getCode() == ResultCode.SUCCESS.getCode()){
                SaveResponse response = SaveResponse.newBuilder().setUpdateNum(result.getData()).build();
                responseObserver.onNext(response);
                responseObserver.onCompleted();
            }
            else
                FunctionUtil.errorHandler(result, responseObserver, "saveBinData");
        }

    }
}
